/*! Tdrag 0.0.1 */
/**
 * Created by Tezml on 2016/5/26
 * You can modify my source code, if you have a good idea or a problem can be encountered by e-mail: tezml@tezml.com to find me.
 * 如果你想在项目中使用该插件，请不要删除该注释。
 */
;(function(root, factory) {
	"use strict";
	if (typeof define === "function" && define.amd) {
		define(["jquery","amazeui"], factory);
	} else if (typeof exports === "object") {
		module.exports = factory(require("jquery"),require("amazeui"));
	} else {
		root.jQuery = factory();
	}
}(this, function($) {
	$.fn.Tdrag = function(opt) {
		var call = {
			scope: null, //父级
			grid: null, //网格
			axis: "all", //上下或者左右
			pos: false, //是否记住位置
			handle: null, //手柄
			moveClass: "tezml", //移动时不换位加的class
			dragChange: false, //是否开启拖拽换位
			changeMode: "point", //point & sort
			cbStart: function() {}, //移动前的回调函数
			cbMove: function() {}, //移动中的回调函数
			cbEnd: function() {}, //移动结束时候的回调函数
			random: false, //是否自动随机排序
			randomInput: null, //点击随机排序的按钮
			animation_options: { //运动时的参数
				duration: 800, //每次运动的时间
				easing: "ease-out" //移动时的特效，ease-out、ease-in、linear
			},
			disable: false, //禁止拖拽
			disableInput: null //禁止拖拽的按钮
		};

		var dragfn = new Dragfn(this, opt);
		if(opt && $.isEmptyObject(opt) == false) {
			dragfn.options = $.extend(call, opt);
		} else {
			dragfn.options = call;
		}

		dragfn.firstRandom = true;
		var ele = dragfn.$element;
		dragfn.pack(ele, false);
		if(dragfn.options.randomInput != null) {
			$(dragfn.options.randomInput).bind("click", function() {
				dragfn.pack(ele, true);
			})
		}
		//加载拓展jquery的函数
		dragfn.loadJqueryfn()
	};

	//依赖构造函数
	var Dragfn = function(ele, opt) {
		this.$element = ele;
		this.options = opt;
	};
	//构造函数方法
	Dragfn.prototype = {
		init: function(obj) {
			var self = this;
			self.ele = self.$element;
			self.handle = $(obj); //手柄
			self.options = self.options;
			self.disable = self.options.disable;
			self._start = false;
			self._move = false;
			self._end = false;
			self.disX = 0;
			self.disY = 0;
			self.zIndex = 1000;
			self.moving = false;
			self.moves = "";

			//父级
			self.box = $.type(self.options.scope) === "string" ? self.options.scope : null;
			//手柄
			if(self.options.handle != null) {
				self.handle = $(obj).find(self.options.handle);
			}

			// 原有三个事件
			// 现改为一个事件
			self.handle.on("mousedown", function(ev) {
				self.start(ev, obj);
				obj.setCapture && obj.setCapture();

				if(self.options.dragChange) {
					$(obj).on("mousemove", function(ev) {
						self.move(ev, obj);
					});
					$(obj).on("mouseup", function(ev) {
						self.end(ev, obj);
					});
				} else {
					$(document).on("mousemove", function(ev) {
						self.move(ev, obj);
					});
					$(document).on("mouseup", function(ev) {
						self.end(ev, obj);
					});
				}
				$(document).unbind("onmousemove");
				$(document).unbind("onmouseup");
				return false;
			});

			// 原代码，因为项目中有 unbind 事件导致此插件失效，所以放入上面每次重新开启
			/*if(self.options.dragChange) {
				$(obj).on("mousemove", function(ev) {
					self.move(ev, obj);
				});
				$(obj).on("mouseup", function(ev) {
					self.end(ev, obj);
				});
			} else {
				$(document).on("mousemove", function(ev) {
					self.move(ev, obj);
				});
				$(document).on("mouseup", function(ev) {
					self.end(ev, obj);
				});
			}*/
		},
		//jquery调取函数时候用
		loadJqueryfn: function() {
			var self = this;
			$.extend({
				//返回按照index排序的回调函数
				sortBox: function(obj) {
					var arr = [];
					for(var s = 0; s < $(obj).length; s++) {
						arr.push($(obj).eq(s));
					}
					for(var i = 0; i < arr.length; i++) {
						for(var j = i + 1; j < arr.length; j++) {
							if(Number(arr[i].attr("index")) > Number(arr[j].attr("index"))) {
								var temp = arr[i];
								arr[i] = arr[j];
								arr[j] = temp;
							}
						}
					}
					return arr
				},
				//随机排序函数
				randomfn: function(obj) {
					self.pack($(obj), true);
				},
				//开启拖拽
				disable_open: function() {
					self.disable = false;
				},
				//禁止拖拽
				disable_cloose: function() {
					self.disable = true;
				}
			});
		},
		toDisable: function() {
			var self = this;
			if(self.options.disableInput != null) {
				$(self.options.disableInput).bind("click", function() {
					if(self.disable == true) {
						self.disable = false
					} else {
						self.disable = true
					}
				})
			}
		},
		start: function(ev, obj) {
			var self = this;
			self.moved = obj;
			if(self.disable == true) {
				return false
			}
			self._start = true;
			var oEvent = ev || event;
			self.disX = oEvent.clientX - obj.offsetLeft;
			self.disY = oEvent.clientY - obj.offsetTop;
			self.options.cbStart();
		},
		move: function(ev, obj) {
			var self = this;
			if(self._start != true) {
				return false
			}
			if(obj != self.moved) {
				return false
			}
			self._move = true;
			var oEvent = ev || event;
			var l = oEvent.clientX - self.disX;
			var t = oEvent.clientY - self.disY;
			//有父级限制
			if(self.box != null) {
				var rule = self.collTestBox(obj, self.box);
				if(l > rule.lmax) {
					l = rule.lmax;
				} else if(l < rule.lmin) {
					l = rule.lmin;
				}
				if(t > rule.tmax) {
					t = rule.tmax;
				} else if(t < rule.tmin) {
					t = rule.tmin;
				}
			}
			if(self.options.axis == "all") {
				obj.style.left = self.grid(obj, l, t).left + 'px';
				obj.style.top = self.grid(obj, l, t).top + 'px';
			} else if(self.options.axis == "y") {
				obj.style.top = self.grid(obj, l, t).top + 'px';
			} else if(self.options.axis == "x") {
				obj.style.left = self.grid(obj, l, t).left + 'px';
			}
			/* if(self.options.changeWhen=="move") {
			     if (self.options.changeMode == "sort") {
			         self.sortDrag(obj);
			     } else if (self.options.changeMode == "point") {
			         self.pointmoveDrag(obj);
			     }
			 }else{
			     self.moveAddClass(obj);
			 }*/
			if(self.options.pos == true) {
				self.moveAddClass(obj);
			}
			self.options.cbMove(obj, self);

		},
		end: function(ev, obj) {
			var self = this;
			if(self._start != true) {
				return false
			}
			if(self.options.changeMode == "sort" && self.options.pos == true) {
				self.sortDrag(obj);
			} else if(self.options.changeMode == "point" && self.options.pos == true) {
				self.pointDrag(obj);
			}
			if(self.options.pos == true) {
				self.animation(obj, self.aPos[$(obj).attr("index")]);
			}
			self.options.cbEnd();
			if(self.options.handle != null) {
				$(obj).find(self.options.handle).unbind("onmousemove");
				$(obj).find(self.options.handle).unbind("onmouseup");
			} else {
				$(obj).unbind("onmousemove");
				$(obj).unbind("onmouseup");
			}
			obj.releaseCapture && obj.releaseCapture();
			self._start = false;

		},
		//算父级的宽高
		collTestBox: function(obj, obj2) {
			var self = this;
			var l1 = 0;
			var t1 = 0;
			var l2 = $(obj2).innerWidth() - $(obj).outerWidth();
			var t2 = $(obj2).innerHeight() - $(obj).outerHeight();
			return {
				lmin: l1, //取的l最小值
				tmin: t1, //取的t最小值
				lmax: l2, //取的l最大值
				tmax: t2 //取的t最大值
			}

		},
		//算父级宽高时候干掉margin
		grid: function(obj, l, t) { //cur:[width,height]
			var self = this;
			var json = {
				left: l,
				top: t
			};
			if($.isArray(self.options.grid) && self.options.grid.length == 2) {
				var gx = self.options.grid[0];
				var gy = self.options.grid[1];
				json.left = Math.floor((l + gx / 2) / gx) * gx;
				json.top = Math.floor((t + gy / 2) / gy) * gy;
				return json
			} else if(self.options.grid == null) {
				return json
			} else {
				console.log("grid参数传递格式错误");
				return false
			}
		},
		findNearest: function(obj) {
			var self = this;
			var iMin = new Date().getTime();
			var iMinIndex = -1;
			var ele = self.ele;
			for(var i = 0; i < ele.length; i++) {
				if(obj == ele[i]) {
					continue;
				}
				if(self.collTest(obj, ele[i])) {
					var dis = self.getDis(obj, ele[i]);
					if(dis < iMin) {
						iMin = dis;
						iMinIndex = i;
					}
				}
			}
			if(iMinIndex == -1) {
				return null;
			} else {
				return ele[iMinIndex];
			}
		},
		getDis: function(obj, obj2) {
			var self = this;
			var l1 = obj.offsetLeft + obj.offsetWidth / 2;
			var l2 = obj2.offsetLeft + obj2.offsetWidth / 2;

			var t1 = obj.offsetTop + obj.offsetHeight / 2;
			var t2 = obj2.offsetTop + obj2.offsetHeight / 2;

			var a = l2 - l1;
			var b = t1 - t2;

			return Math.sqrt(a * a + b * b);
		},
		collTest: function(obj, obj2) {
			var self = this;
			var l1 = obj.offsetLeft;
			var r1 = obj.offsetLeft + obj.offsetWidth;
			var t1 = obj.offsetTop;
			var b1 = obj.offsetTop + obj.offsetHeight;

			var l2 = obj2.offsetLeft;
			var r2 = obj2.offsetLeft + obj2.offsetWidth;
			var t2 = obj2.offsetTop;
			var b2 = obj2.offsetTop + obj2.offsetHeight;

			if(r1 < l2 || r2 < l1 || t2 > b1 || b2 < t1) {
				return false;
			} else {
				return true;
			}
		},
		//初始布局转换
		pack: function(ele, click) {
			var self = this;
			self.toDisable();
			if(self.options.pos == false) {
				for(var i = 0; i < ele.length; i++) {
					$(ele[i]).css("position", "absolute");
					$(ele[i]).css("margin", "0");
					self.init(ele[i]);
				}
			} else if(self.options.pos == true) {
				var arr = [];
				if(self.options.random || click) {
					while(arr.length < ele.length) {
						var n = self.rnd(0, ele.length);
						if(!self.finInArr(arr, n)) { //没找到
							arr.push(n);
						}
					}
				}
				if(self.options.random == false || click != true) {
					var n = 0;
					while(arr.length < ele.length) {
						arr.push(n);
						n++
					}
				}

				//如果是第二次以后随机列表，那就重新排序后再随机，因为我智商不够使，不会排了
				if(self.firstRandom == false) {
					var sortarr = [];
					var n = 0;
					while(sortarr.length < ele.length) {
						sortarr.push(n);
						n++
					}
					for(var i = 0; i < ele.length; i++) {
						$(ele[i]).attr("index", sortarr[i]);
						$(ele[i]).css("left", self.aPos[sortarr[i]].left);
						$(ele[i]).css("top", self.aPos[sortarr[i]].top);
					}
				}

				//布局转化
				self.aPos = [];
				if(self.firstRandom == false) {
					//不是第一次
					for(var j = 0; j < ele.length; j++) {
						self.aPos[j] = {
							left: ele[$(ele).eq(j).attr("index")].offsetLeft,
							top: ele[$(ele).eq(j).attr("index")].offsetTop
						};
					}
				} else {
					//第一次
					for(var j = 0; j < ele.length; j++) {
						self.aPos[j] = {
							left: ele[j].offsetLeft,
							top: ele[j].offsetTop
						};
					}
				}
				//第二个循环布局转化
				for(var i = 0; i < ele.length; i++) {
					$(ele[i]).attr("index", arr[i]);
					$(ele[i]).css("left", self.aPos[arr[i]].left);
					$(ele[i]).css("top", self.aPos[arr[i]].top);
					$(ele[i]).css("position", "absolute");
					$(ele[i]).css("margin", "0");
					self.init(ele[i]);
				}
				self.firstRandom = false;
			}
		},
		//移动时候加class
		moveAddClass: function(obj) {
			var self = this;
			var oNear = self.findNearest(obj);
			$(self.$element).removeClass(self.options.moveClass);
			if(oNear && $(oNear).hasClass(self.options.moveClass) == false) {
				$(oNear).addClass(self.options.moveClass);
			}

		},
		//给li排序
		sort: function() {
			var self = this;
			var arr_li = [];
			for(var s = 0; s < self.$element.length; s++) {
				arr_li.push(self.$element[s]);
			}
			for(var i = 0; i < arr_li.length; i++) {
				for(var j = i + 1; j < arr_li.length; j++) {
					if(Number($(arr_li[i]).attr("index")) > Number($(arr_li[j]).attr("index"))) {
						var temp = arr_li[i];
						arr_li[i] = arr_li[j];
						arr_li[j] = temp;
					}
				}
			}
			return arr_li;
		},
		//点对点的方式换位
		pointDrag: function(obj) {
			var self = this;
			//先拍序
			var oNear = self.findNearest(obj);
			if(oNear) {
				self.animation(obj, self.aPos[$(oNear).attr("index")]);
				self.animation(oNear, self.aPos[$(obj).attr("index")]);
				var tmp;
				tmp = $(obj).attr("index");
				$(obj).attr("index", $(oNear).attr("index"));
				$(oNear).attr("index", tmp);
				$(oNear).removeClass(self.options.moveClass);
			} else if(self.options.changeWhen == "end") {
				self.animation(obj, self.aPos[$(obj).attr("index")]);
			}

		},
		//排序的方式换位
		sortDrag: function(obj) {
			var self = this;
			//先拍序
			var arr_li = self.sort();
			//换位置
			var oNear = self.findNearest(obj);
			if(oNear) {
				if(Number($(oNear).attr("index")) > Number($(obj).attr("index"))) {
					//前换后
					var obj_tmp = Number($(obj).attr("index"));
					$(obj).attr("index", Number($(oNear).attr("index")) + 1);
					for(var i = obj_tmp; i < Number($(oNear).attr("index")) + 1; i++) {
						self.animation(arr_li[i], self.aPos[i - 1]);
						self.animation(obj, self.aPos[$(oNear).attr("index")]);
						$(arr_li[i]).removeClass(self.options.moveClass);
						$(arr_li[i]).attr("index", Number($(arr_li[i]).attr("index")) - 1);
					}

				} else if(Number($(obj).attr("index")) > Number($(oNear).attr("index"))) {
					//后换前
					var obj_tmp = Number($(obj).attr("index"));
					$(obj).attr("index", $(oNear).attr("index"));
					for(var i = Number($(oNear).attr("index")); i < obj_tmp; i++) {
						self.animation(arr_li[i], self.aPos[i + 1]);
						self.animation(obj, self.aPos[Number($(obj).attr("index"))]);
						$(arr_li[i]).removeClass(self.options.moveClass);
						$(arr_li[i]).attr("index", Number($(arr_li[i]).attr("index")) + 1);
					}
				}
			} else {
				self.animation(obj, self.aPos[$(obj).attr("index")]);
			}

		},
		//运动函数(后期再加参数)
		animation: function(obj, json) {
			var self = this;
			//考虑默认值
			var options = self.options.animation_options;
			/*|| {};
			               options.duration=self.options.animation_options.duration || 800;
			               options.easing=options.easing.duration.easing || 'ease-out';*/
			var self = this;
			var count = Math.round(options.duration / 30);
			var start = {};
			var dis = {};
			for(var name in json) {
				start[name] = parseFloat(self.getStyle(obj, name));
				if(isNaN(start[name])) {
					switch(name) {
						case 'left':
							start[name] = obj.offsetLeft;
							break;
						case 'top':
							start[name] = obj.offsetTop;
							break;
						case 'width':
							start[name] = obj.offsetWidth;
							break;
						case 'height':
							start[name] = obj.offsetHeight;
							break;
						case 'marginLeft':
							start[name] = obj.offsetLeft;
							break;
						case 'borderWidth':
							start[name] = 0;
							break;
							//...
					}
				}
				dis[name] = json[name] - start[name];
			}

			var n = 0;

			clearInterval(obj.timer);
			obj.timer = setInterval(function() {
				n++;
				for(var name in json) {
					switch(options.easing) {
						case 'linear':
							var a = n / count;
							var cur = start[name] + dis[name] * a;
							break;
						case 'ease-in':
							var a = n / count;
							var cur = start[name] + dis[name] * a * a * a;
							break;
						case 'ease-out':
							var a = 1 - n / count;
							var cur = start[name] + dis[name] * (1 - a * a * a);
							break;
					}

					if(name == 'opacity') {
						obj.style.opacity = cur;
						obj.style.filter = 'alpha(opacity:' + cur * 100 + ')';
					} else {
						obj.style[name] = cur + 'px';
					}
				}

				if(n == count) {
					clearInterval(obj.timer);
					options.complete && options.complete();
				}
			}, 30);
		},
		getStyle: function(obj, name) {
			return(obj.currentStyle || getComputedStyle(obj, false))[name];
		},
		//随机数
		rnd: function(n, m) {
			return parseInt(Math.random() * (m - n) + n);
		},
		//在数组中找
		finInArr: function(arr, n) {
			for(var i = 0; i < arr.length; i++) {
				if(arr[i] == n) { //存在
					return true;
				}
			}
			return false;
		}
	}
}));